home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / CAGD_ARC.C < prev    next >
C/C++ Source or Header  |  1991-05-26  |  5KB  |  131 lines

  1. /******************************************************************************
  2. * Cagd_Arc.c - Curve representation of arcs and circles                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Jun. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #ifdef __MSDOS__
  8. #include <stdlib.h>
  9. #endif /* __MSDOS__ */
  10.  
  11. #include <ctype.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "cagd_loc.h"
  15.  
  16. #define UNIT_CIRCLE_ORDER 3
  17. #define UNIT_CIRCLE_LENGTH 9      /* Nine control points in the unit circle. */
  18.  
  19. static int UnitCircleKnots[UNIT_CIRCLE_ORDER + UNIT_CIRCLE_LENGTH] =
  20.                     { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 };
  21. static int UnitCircleX[UNIT_CIRCLE_LENGTH] = { 1, 1, 0, -1, -1, -1, 0, 1, 1 };
  22. static int UnitCircleY[UNIT_CIRCLE_LENGTH] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
  23.  
  24. /******************************************************************************
  25. * Creates an arc at the specified position as a rational Bezier curve.          *
  26. *   The arc is assumed to be less than 180 degrees from Start to End in the   *
  27. * shorter path as arc where Center as arc center.                  *
  28. ******************************************************************************/
  29. CagdCrvStruct *BzrCrvCreateArc(CagdPtStruct *Start, CagdPtStruct *Center,
  30.                                  CagdPtStruct *End)
  31. {
  32.     int i;
  33.     CagdCrvStruct
  34.     *Arc = BzrCrvNew(3, CAGD_PT_P3_TYPE);
  35.     CagdRType Len, CosAlpha, Radius,
  36.     **Points = Arc -> Points;
  37.     CagdVecStruct V1, V2, V;
  38.  
  39.     /* Copy first point. */
  40.     Points[X][0] = Start -> Pt[0];
  41.     Points[Y][0] = Start -> Pt[1];
  42.     Points[Z][0] = Start -> Pt[2];
  43.     Points[W][0] = 1.0;
  44.  
  45.     /* Copy last point. */
  46.     Points[X][2] = End -> Pt[0];
  47.     Points[Y][2] = End -> Pt[1];
  48.     Points[Z][2] = End -> Pt[2];
  49.     Points[W][2] = 1.0;
  50.  
  51.     /* Compute position of middle point. */
  52.     Len = 0.0;
  53.     for (i = 0; i < 3; i++) {
  54.     V1.Vec[i] = Start -> Pt[i] - Center -> Pt[i];
  55.     V2.Vec[i] = End -> Pt[i] - Center -> Pt[i];
  56.     V.Vec[i] = V1.Vec[i] + V2.Vec[i];
  57.     Len += SQR(V.Vec[i]);
  58.     }
  59.  
  60.     if (APX_EQ(Len, 0.0)) {
  61.     CagdCrvFree(Arc);
  62.     FATAL_ERROR(CAGD_ERR_180_ARC);
  63.     return NULL;
  64.     }
  65.     else
  66.     Len = sqrt(Len);
  67.  
  68.     for (i = 0; i < 3; i++) V.Vec[i] /= Len;
  69.  
  70.     /* Compute cosine alpha (where alpha is the angle between V and V1. */
  71.     Radius = sqrt(DOT_PROD(V1.Vec, V1.Vec));
  72.     CosAlpha = DOT_PROD(V1.Vec, V.Vec) / Radius;
  73.  
  74.     CAGD_DIV_VECTOR(V, CosAlpha);
  75.     CAGD_MULT_VECTOR(V, Radius);
  76.  
  77.     /* And finally fill in the middle point with CosAlpha as the Weight. */
  78.     Points[X][1] = (Center -> Pt[0] + V.Vec[0]) * CosAlpha;
  79.     Points[Y][1] = (Center -> Pt[1] + V.Vec[1]) * CosAlpha;
  80.     Points[Z][1] = (Center -> Pt[2] + V.Vec[2]) * CosAlpha;
  81.     Points[W][1] = CosAlpha;
  82.  
  83.     return Arc;
  84. }
  85.  
  86. /******************************************************************************
  87. * Creates a circle at the specified position as a rational Bspline curve.     *
  88. *   Construct a circle as 4 90 degrees arcs of rationa bezier segments using  *
  89. * the constants defined above.                              *
  90. ******************************************************************************/
  91. CagdCrvStruct *BspCrvCreateUnitCircle(void)
  92. {
  93.     int i;
  94.     CagdRType Weight,
  95.         W45 = sin( M_PI / 4.0 );
  96.     CagdCrvStruct
  97.     *Circle = BspCrvNew(UNIT_CIRCLE_LENGTH, UNIT_CIRCLE_ORDER,
  98.                                   CAGD_PT_P3_TYPE);
  99.     CagdRType
  100.     **Points = Circle -> Points;
  101.  
  102.     for (i = 0; i < UNIT_CIRCLE_LENGTH + UNIT_CIRCLE_ORDER; i++)
  103.     Circle -> KnotVector[i] = UnitCircleKnots[i];
  104.  
  105.     for (i = 0; i < UNIT_CIRCLE_LENGTH; i++) {
  106.     Weight = Points[W][i] = i % 2 ? W45: 1.0;
  107.     Points[X][i] = UnitCircleX[i] * Weight;
  108.     Points[Y][i] = UnitCircleY[i] * Weight;
  109.     Points[Z][i] = 0.0;
  110.     }
  111.  
  112.     return Circle;
  113. }
  114.  
  115.  
  116. /******************************************************************************
  117. * Creates a circle at the specified position as a rational bezier curve.      *
  118. ******************************************************************************/
  119. CagdCrvStruct *BspCrvCreateCircle(CagdPtStruct *Center, CagdRType Radius)
  120. {
  121.     CagdPtStruct OriginPt;
  122.     CagdCrvStruct *Circle = BspCrvCreateUnitCircle();
  123.  
  124.     /* Do it in two stages: 1. scale, 2. translate */
  125.     OriginPt.Pt[0] = OriginPt.Pt[1] = OriginPt.Pt[2] = 0.0;
  126.     CagdCrvTransform(Circle, OriginPt.Pt, Radius);
  127.     CagdCrvTransform(Circle, Center -> Pt, 1.0);
  128.  
  129.     return Circle;
  130. }
  131.